package server;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.Socket;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author junbao
 */
public class RequestProcessor extends Thread{

    private Socket socket;
    private ServerMapper serverMapper;
    private Map<String, HttpServlet> servletMap;

    public RequestProcessor(Socket socket, ServerMapper serverMapper) {
        this.socket = socket;
        this.serverMapper = serverMapper;
        this.servletMap = new HashMap<>();
        //run();
    }

    @Override
    public void run() {
        try {
            InputStream inputStream = socket.getInputStream();
            // 封装对象
            Request request = new Request(inputStream);
            Response response = new Response(socket.getOutputStream());

            if(serverMapper.getHostName().equals(request.getHost())) {
                boolean flag = true;
                String project = "";
                if (!request.getUrl().isEmpty()) {
                    String[] split = request.getUrl().split("/");
                    if (split.length > 2) {
                        project = split[1];
                        if(serverMapper.getProjectList().contains(project) && (!request.getUrl().contains(".html"))) {
                            loadServlet(project);
                            HttpServlet httpServlet = servletMap.get("/" + split[2]);
                            httpServlet.service(request, response);
                            flag = false;
                        }
                    }
                }

                if (flag) {
                    response.outputHtml(request.getUrl(), serverMapper.getWebappPath());
                }
            }
            socket.close();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void loadServlet(String project) throws IOException {

        String path = this.serverMapper.getWebappPath() +  "/" + project;
        InputStream configStream = new FileInputStream(path + "/web.xml");

        //InputStream resourceAsStream = this.getClass().getClassLoader().getResourceAsStream("web.xml");
        SAXReader saxReader = new SAXReader();

        try {
            Document document = saxReader.read(configStream);
            Element rootElement = document.getRootElement();

            List<Element> list = rootElement.selectNodes("//servlet");
            for (int i = 0; i < list.size(); i++) {
                Element element =  list.get(i);
                // <servlet-name>lagou</servlet-name>
                Element servletNameElement = (Element) element.selectSingleNode("servlet-name");
                String servletName = servletNameElement.getStringValue();
                // <servlet-class>server.LagouServlet</servlet-class>
                Element servletClassElement = (Element) element.selectSingleNode("servlet-class");
                String servletClass = servletClassElement.getStringValue();

                // 根据servlet-name的值找到url-pattern
                Element servletMapping = (Element) rootElement.selectSingleNode("/web-app/servlet-mapping[servlet-name='" + servletName + "']");
                String urlPattern = servletMapping.selectSingleNode("url-pattern").getStringValue();

                ClassLoaderMini loader = new ClassLoaderMini(
                        path + "/server/LagouServlet.class");
                Class<?> clazz = loader.loadClass(servletClass);
                servletMap.put(urlPattern, (HttpServlet) clazz.newInstance());
                //servletMap.put(urlPattern, (HttpServlet) Class.forName(servletClass).newInstance());
            }
        } catch (DocumentException | ClassNotFoundException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        }
    }
}
